/*
 * Group:PrePool K9-357 
 * 8/2010
 */
package core;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import org.apache.log4j.Logger;

import util.Constants;

/**
 *
 */
public class IfoFile {
	private static Logger LOG = Logger.getLogger("core.IfoFile");
	private String strFileName; // path to the ".ifo" file

	// following properties are stored in ".ifo" file
	private long longWordCount = 0; // number of entries stored in ".idx" file
	private String strSameTypeSequence = Constants.BLANK_STRING;
	private long longIdxFileSize = 0; // size of ".idx" file

	private String strVersion = Constants.BLANK_STRING; // version of dictionary
	private String strBookname = Constants.BLANK_STRING; // name of dictionary
	private String strAuthor = Constants.BLANK_STRING;
	private String strWebsite = Constants.BLANK_STRING;
	private String strDescription = Constants.BLANK_STRING;
	private String strDate = Constants.BLANK_STRING;

	public boolean boolIsLoaded = false; // decide if ".ifo" file is loaded

	public long getLongWordCount() {
		return longWordCount;
	}

	public void setLongWordCount(long longWordCount) {
		this.longWordCount = longWordCount;
	}

	public long getLongIdxFileSize() {
		return longIdxFileSize;
	}

	public void setLongIdxFileSize(long longIdxFileSize) {
		this.longIdxFileSize = longIdxFileSize;
	}

	public String getStrBookname() {
		return strBookname;
	}

	public void setStrBookname(String strBookname) {
		this.strBookname = strBookname;
	}

	/**
	 * Constructor
	 * 
	 * @param fileName
	 *            Ifo file's URL
	 */
	public IfoFile(String fileName) {
		this.strFileName = fileName;
		load();
	}

	/**
	 * load .ifo file
	 */
	public void load() {
		// check if the above properties are loaded
		if (boolIsLoaded) {
			return;
		}
		// load the properties
		try {
			// initiate a file reader
			DataInputStream dt = new DataInputStream(new BufferedInputStream(
					new FileInputStream(strFileName)));
			byte[] bt = new byte[500];
			dt.read(bt); // read entire info file
			dt.close();
			String strInput = new String(bt, "UTF8"); // convert to utf8 string
			strVersion = getStringForKey("version=", strInput);

			// get version
			if (strVersion.equals("2.4.2") == false) { // only work on version
				// 2.4.2
				return;
			}
			// get number of entries
			if ((longWordCount = getLongForKey("wordcount=", strInput)) < 0) {
				// get
				// number
				// of
				// entries
				// and
				// check
				return;
			}
			// get size of ".idx" file
			if ((longIdxFileSize = getLongForKey("idxfilesize=", strInput)) < 0) {
				// get
				// size
				// of
				// index
				// file
				// and
				// check
				return;
			}
			// get same type sequence
			strSameTypeSequence = getStringForKey("sametypesequence=", strInput);
			// get name of dictionary
			strBookname = getStringForKey("bookname=", strInput);

			if (strBookname == null) {
				return;
			}
			// get name of author
			strAuthor = getStringForKey("author=", strInput);
			// get name of Website
			strWebsite = getStringForKey("website=", strInput);
			// get description
			strDescription = getStringForKey("description=", strInput);
			strDate = getStringForKey("date=", strInput);
			// make sure that ifo file is loaded successfully
			boolIsLoaded = longWordCount > 0;
		} catch (Exception ex) {
			LOG.error("load", ex);
		}
	}

	/**
	 * load the properties again
	 */
	public void reload() {
		boolIsLoaded = false;
		load();
	}

	/**
	 * find a long number follows the key in a string
	 * 
	 * @param strKey
	 * @param str
	 * @return
	 */
	long getLongForKey(String strKey, String str) {
		try {
			return Long.parseLong(getStringForKey(strKey, str));
		} catch (Exception ex) {
			LOG.error("getLongForKey", ex);
			return 0;
		}
	}

	/**
	 * find a string follows the key in a string
	 * 
	 * @param strKey
	 * @param str
	 * @return
	 */
	String getStringForKey(String strKey, String str) {
		int keyLen = strKey.length();
		int startPos = str.indexOf(strKey) + keyLen;

		if (startPos < keyLen) {
			return null;
		}
		char[] strStr = str.toCharArray();
		int endPos = startPos - 1;
		while (strStr[++endPos] != '\n' && strStr[endPos] != '\0')
			;
		return new String(strStr, startPos, endPos - startPos);
	}

	/**
	 * write info file according to a specific file name
	 * 
	 * @param fileName
	 * @return
	 */
	boolean write(String fileName) {
		try {
			FileOutputStream fos = new FileOutputStream(fileName);
			OutputStreamWriter opw = new OutputStreamWriter(fos, "UTF8");
			opw.write("StarDict's dict ifo file\n");
			opw.write("version=" + strVersion + "\n");
			opw.write("wordcount=" + longWordCount + "\n");
			opw.write("idxfilesize=" + longIdxFileSize + "\n");
			opw.write("bookname=" + strBookname + "\n");
			opw.write("author=" + strAuthor + "\n");
			opw.write("website=" + strWebsite + "\n");
			opw.write("description=" + strDescription + "\n");
			opw.write("date=" + strDate + "\n");
			opw.write("sametypesequence=" + strSameTypeSequence + "\n");
			opw.flush();
			opw.close();
			fos.close();
		} catch (Exception ex) {
			LOG.error("write", ex);
			return false;
		}
		return true;
	}

	/**
	 * @return
	 */
	boolean write() {
		return write(strFileName);
	}
}
